package com.quanyan.club.operate.service.impl;

import com.alibaba.fastjson.JSON;
import com.quanyan.api.APIRequest;
import com.quanyan.api.APIResponse;
import com.quanyan.api.enums.AssetsType;
import com.quanyan.assets.entity.CouponInfoVo;
import com.quanyan.assets.entity.ObtainCouponsParamsVo;
import com.quanyan.assets.entity.TbUserAssets;
import com.quanyan.assets.enums.ActivityCouponType;
import com.quanyan.assets.request.ReqUserAccumulateModify;
import com.quanyan.assets.request.ReqUserInfo;
import com.quanyan.assets.response.RespUserAccumulateModify;
import com.quanyan.assets.service.CouponService;
import com.quanyan.assets.service.UserAssetsService;
import com.quanyan.club.cache.ClubRedisTemplate;
import com.quanyan.club.constants.ClubConstants;
import com.quanyan.club.entity.db.*;
import com.quanyan.club.mapper.*;
import com.quanyan.club.operate.entity.RespHitPrizeInfo;
import com.quanyan.club.operate.service.LotteryService;
import com.quanyan.club.operate.util.LotteryRateListUtil;
import com.quanyan.club.service.CppService;
import com.quanyan.club.service.impl.BaseServiceImpl;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.redisCluster.config.RedisTemplate;
import com.quanyan.redisCluster.utils.RedisKey;
import com.quanyan.sms.service.SmsService;
import com.quanyan.user.response.RespUserInfoBase;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by zhuo.shi on 2016/12/7.
 *
 * 抽奖活动
 */
@Service
public class LotteryServiceImpl extends BaseServiceImpl implements LotteryService{

    public static final Logger logger = LoggerFactory.getLogger(LotteryServiceImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ClubRedisTemplate clubRedisTemplate;
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    @Autowired
    private UserAssetsService userAssetsService;
    @Autowired
    private TbOperateLotteryPrizeItemsMapper lotteryPrizeItemsMapper;
    @Autowired
    private TbOperateLotteryPrizeRecordMapper lotteryPrizeRecordMapper;
    @Autowired
    private TbClubMapper clubMapper;
    @Autowired
    private TbClubActivitySettlementMapper clubActivitySettlementMapper;
    @Autowired
    private ThreadPoolTaskExecutor executor;
    @Autowired
    private TbOperateLotteryLimitMapper lotteryLimitMapper;
    @Autowired
    private CppService cppService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private CouponService couponService;
    @Autowired
    private TbSystemParametersMapper systemParametersMapper;
    @Autowired
    private TbOperateLotteryTimesMapper operateLotteryTimesMapper;

    private static final RedisKey LOTTERY_REDIS_KEY = new RedisKey(Constants.CLUB_SYSTEM, "lottery");

    @Override
    public APIResponse queryLotteryPrizeItems2(Integer uid) {
        Map<String, Object> result = new HashMap<>();
        if (uid != null) {
            TbOperateLotteryTimesExample example = new TbOperateLotteryTimesExample();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            example.createCriteria()
                    .andUidEqualTo(uid);
//                    .andEffectiveDateEqualTo(df.format(new Date()));
            List<TbOperateLotteryTimes> times = operateLotteryTimesMapper.selectByExample(example);
            if (!CollectionUtils.isEmpty(times)){
                result.put("count", times.get(0).getNum());
            }
        }

        TbOperateLotteryPrizeItemsExample example = new TbOperateLotteryPrizeItemsExample();
        example.createCriteria().andTypeEqualTo(2);
        example.setOrderByClause(" id asc");
        result.put("prizeItem", lotteryPrizeItemsMapper.selectByExample(example));
        return APIResponse.returnSuccess(result);
    }

    @Override
    @Transactional
    public APIResponse drawLottery2(int uid){
        //1. 验证平台用户，抽奖时间
        RespUserInfoBase userInfo = getUserInfoBase(uid);
        if (userInfo == null){
            return APIResponse.returnFail(100, "用户不存在");
        }
//        Date now = new Date();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        RedisKey redisKey = new RedisKey(Constants.CLUB_SYSTEM, getLotteryNLRedisKey(uid));
//        try {
//            if (redisTemplate.exists(redisKey)) {
//                int dcount = redisTemplate.get(redisKey)==null?0:(Integer.valueOf((redisTemplate.get(redisKey).toString())));
//                if (dcount >= 20) {
//                    return APIResponse.returnFail(103, "今天已经抽够20次了，明天再来吧！");
//                }
//            }

//            TbSystemParametersExample sysExample = new TbSystemParametersExample();
//            sysExample.createCriteria().andParamKeyEqualTo("operate.lottery.newyear.start.time");
//            TbSystemParameters startTime = systemParametersMapper.selectByExample(sysExample).get(0);
//            if (now.before(sdf.parse(startTime.getParamValue()))) {
//                return APIResponse.returnFail(101, "抽奖活动未开始");
//            }
//            sysExample.clear();
//            sysExample.createCriteria().andParamKeyEqualTo("operate.lottery.newyear.end.time");
//            TbSystemParameters endTime = systemParametersMapper.selectByExample(sysExample).get(0);
//            if (now.after(sdf.parse(endTime.getParamValue()))){
//                return APIResponse.returnFail(101, "抽奖活动已经结束");
//            }
//        } catch (ParseException e) {
//            logger.warn("未配置抽奖活动开始结束时间");
//            return APIResponse.returnFail(101, "活动还未开始");
//        }
//        TbOperateLotteryLimitExample limitExample = new TbOperateLotteryLimitExample();
//        limitExample.createCriteria().andMobileEqualTo(userInfo.getMobile());
//        if (lotteryLimitMapper.countByExample(limitExample) > 0){
//            return APIResponse.returnFail(106,  "嘿嘿，百灵鸟的小伙伴好好努力工作吧，就是不让你抽奖！");
//        }

        //2. 扣除除抽奖次数
        Map<String, Object> param = new HashMap<>();
        param.put("uid", uid);
//        param.put("effectiveDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        int ret = sqlSessionTemplate.update("updateLotteryPrizeTimes", param);
        if (ret <= 0){
            return APIResponse.returnFail(102, "抽奖次数不足");
        }

        //3. 开始抽奖:
        RespHitPrizeInfo hitPrizeInfo = new RespHitPrizeInfo();  //中奖信息
        hitPrizeInfo.setUid(uid);
        hitPrizeInfo.setMobile(userInfo.getMobile());
        //奖品列表
        TbOperateLotteryPrizeItemsExample itemExample = new TbOperateLotteryPrizeItemsExample();
        itemExample.createCriteria().andTypeEqualTo(2); //spring 趴 抽奖
        itemExample.setOrderByClause(" rate asc");
        List<TbOperateLotteryPrizeItems> prizeItems = lotteryPrizeItemsMapper.selectByExample(itemExample);
        Map<Integer, Double> IDRateMap = new TreeMap<>();
        for (TbOperateLotteryPrizeItems prizeItem : prizeItems){
            IDRateMap.put(prizeItem.getId(), prizeItem.getRate());
        }
        //算出此次中奖的奖品
        LotteryRateListUtil lotteryRateListUtil = new LotteryRateListUtil(IDRateMap);
        int prizeId = lotteryRateListUtil.hitLotteryRate();
        TbOperateLotteryPrizeItems hitPrizeItem = lotteryPrizeItemsMapper.selectByPrimaryKey(prizeId);
        if (hitPrizeItem == null){
            return APIResponse.returnFail(101, "抽奖活动未开始");  //无此奖品
        }
        logger.warn("抽中：prizeId=" + prizeId + ", prizeName=" + hitPrizeItem.getPrizeDesc());
        boolean hitPrize = false;
        if (hitPrizeItem.getIsAward()){        //中奖奖品不是谢谢参与之类
            //扣减库存
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("prizeId", prizeId);
            int updateRet = sqlSessionTemplate.update("updateLotteryPrizeNumberNewYear", paramMap);
            if (updateRet <= 0) {
                logger.warn("prizeId=" + prizeId + "没有库存！");
                hitPrize = false;           //未中奖： 奖品没有库存，算此人谢谢参与
            } else {                        //中  奖： 记录中奖信息
                hitPrizeInfo.setPrizeId(prizeId);
                hitPrizeInfo.setPrizeName(hitPrizeItem.getPrizeDesc());
                hitPrizeInfo.setPrizeLevel(hitPrizeItem.getLevelName());
                hitPrize = true;
            }
        }
        if (!hitPrize) {        //没有中奖，给谢谢参与
            itemExample.clear();
            itemExample.createCriteria().andTypeEqualTo(2).andIsAwardEqualTo(false);
            TbOperateLotteryPrizeItems blankPrize = lotteryPrizeItemsMapper.selectByExample(itemExample).get(0);
            hitPrizeInfo.setPrizeId(blankPrize.getId());
            hitPrizeInfo.setPrizeLevel(blankPrize.getLevelName());
            hitPrizeInfo.setPrizeName(blankPrize.getPrizeDesc());
        }

        //4. 记录抽奖信息，发虚拟奖品
        TbOperateLotteryPrizeRecord record = new TbOperateLotteryPrizeRecord();
        record.setCostEggs(0);
        record.setMobile(userInfo.getMobile());
        record.setUid(userInfo.getUid());
        record.setPrizeItemId(hitPrizeItem.getId());
        record.setType(2);       //新年抽奖
        if (hitPrize) {     //如果中奖了
            record.setPrizeName(hitPrizeItem.getPrizeDesc());
            record.setHitPrize(true);

            int level = hitPrizeItem.getLevel();
            try {
                if (level < 6) {
                    //推送消息，发短信
                    cppService.pushClubCommonMsg(
                            userInfo.getIcon(),
                            "恭喜您，在春季运动趴抽奖活动中抽中了\"" + hitPrizeItem.getPrizeDesc() + "\"，百灵鸟工作人员将在7个工作日内通过电话或微信与您联系，请保持手机畅通！",
                            Arrays.asList(userInfo.getUid()));
                }
                //smsService.sendMessageToPhone(userInfo.getMobile(), SmsApi.MESSAGE_TEMPLATE_OPERATIVE_NEWYEAR_LOTTERY_NOTICE, new String[]{"\"" + hitPrizeItem.getPrizeDesc() + "\""}, true);
            }catch (Exception e){
                e.printStackTrace();
                logger.warn("发送中奖消息异常：uid={}, msg={}, prizeId=", uid, e.getMessage(), hitPrizeItem.getId());
            }

            //如果是优惠券，发送优惠券到此用户账户
            if (level == 6 || level == 7) {
                ObtainCouponsParamsVo vo = new ObtainCouponsParamsVo();
                vo.setUid(uid);
                if (level == 6) {
                    vo.setActivityCouponType(ActivityCouponType.SPRING_SPORT_DISCOUNT_5);
                }
                if (level == 7) {
                    vo.setActivityCouponType(ActivityCouponType.SPRING_SPORT_10);
                }
                APIResponse<CouponInfoVo> counponResp = couponService.obtainCoupons(vo);
                if (!counponResp.isRet()) {
                    logger.warn("发中奖优惠券失败：uid={}, prizeId={}, return={}", uid, prizeId, JSON.toJSON(counponResp));
                }else {
                    logger.warn("发中奖优惠券：uid={}, prizeId={}, 发放优惠券成功", uid, prizeId);
                        cppService.pushClubCommonMsg(
                            userInfo.getIcon(),
                            "恭喜您，获得\"" + hitPrizeItem.getPrizeDesc() + "\"，请稍后去百灵鸟钱包内查收！",
                            Arrays.asList(userInfo.getUid()));
                }
            }
            //增加一次抽奖次数
            if (level == 8 || level == 9){
                int addret = sqlSessionTemplate.update("addLotteryPrizeTimes", param);
                if (addret != 1){
                    logger.warn("用户{}， mobile={}，抽中了+1次抽奖，增加不成功", uid, userInfo.getMobile());
                }else {
                    logger.warn("用户{}， mobile={}，抽中了+1次抽奖，增加成功！", uid, userInfo.getMobile());
                }
            }
        }else {
            record.setHitPrize(false);
            record.setPrizeName("谢谢参与");
        }
        lotteryPrizeRecordMapper.insertSelective(record);
        hitPrizeInfo.setRid(record.getId());

        return APIResponse.returnSuccess(hitPrizeInfo);
    }

    @Override
    public List<TbOperateLotteryPrizeRecord> queryHitRecordList2() {
        List<TbOperateLotteryPrizeRecord> records = new ArrayList<>();
        TbOperateLotteryPrizeRecordExample example = new TbOperateLotteryPrizeRecordExample();
        example.createCriteria()
                .andTypeEqualTo(2)
                .andHitPrizeEqualTo(true);
        example.setOrderByClause("id desc");
        records = lotteryPrizeRecordMapper.selectByExample(example);
        return records;
    }


    @Override
    public APIResponse queryLotteryPrizeItems(Integer uid) {

//        if (uid != null) {
//            APIResponse validateResp = validateDrawLottery(uid);
//            if (!validateResp.isRet()) {
//                return validateResp;
//            }
//        }

        TbOperateLotteryPrizeItemsExample example = new TbOperateLotteryPrizeItemsExample();
        example.createCriteria().andTypeEqualTo(0);
        example.setOrderByClause(" id asc");
        return APIResponse.returnSuccess(lotteryPrizeItemsMapper.selectByExample(example));
    }

    @Override
    public APIResponse queryLotteryPrizeItemsNewYear(Integer uid) {
        TbOperateLotteryPrizeItemsExample example = new TbOperateLotteryPrizeItemsExample();
        example.createCriteria().andTypeEqualTo(1);
        example.setOrderByClause(" id asc");

        Map<String, Object> map = new HashMap<>();
        map.put("prizeItem", lotteryPrizeItemsMapper.selectByExample(example));

        APIRequest<ReqUserInfo> reqUserInfoAPIRequest = new APIRequest<>();
        ReqUserInfo reqUserInfo = new ReqUserInfo();
        reqUserInfo.setAssetsType(AssetsType.ASSETS_EGGS.getId().byteValue());
        reqUserInfo.setUid(uid);
        reqUserInfoAPIRequest.setData(reqUserInfo);
        APIResponse<List<TbUserAssets>> response = userAssetsService.getUserAccumulateList(reqUserInfoAPIRequest);
        if (!response.isRet() || response.getData() == null || response.getData().isEmpty()){
            return APIResponse.returnFail(104, "获取个人鸟蛋失败！");
        }
        List<TbUserAssets> userAssetses = response.getData();
        map.put("egg", userAssetses.get(0).getAccumulate());
        return APIResponse.returnSuccess(map);
    }

    /**
     * 生成奖品库存的redis key
     */
    private RedisKey getLotteryUidRedisKey(int uid){
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
        return new RedisKey(Constants.CLUB_SYSTEM, "lottery:uid:" + sf.format(new Date()) + ":" + uid);
    }

    /**
     * 生成免费抽奖标记redis key
     */
    private RedisKey getFreeLotteryTagRedisKey(int uid){
        return new RedisKey(Constants.CLUB_SYSTEM, "lottery:tagusedfree:" + uid);
    }

    /**
     * 新年抽奖，每天限制10次
     * @param uid
     * @return
     */
    private String getLotteryNLRedisKey(int uid){
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
        return "lottery:newyeardl:" + sf.format(new Date()) + ":" + uid;
    }

    /**
     * 新年大转盘抽奖
     * @param uid   用户id
     * @return  中奖信息
     */
    @Override
    public APIResponse drawLotteryNewYear(int uid) {


        //1. 验证平台用户，抽奖时间
        RespUserInfoBase userInfo = getUserInfoBase(uid);
        if (userInfo == null){
            return APIResponse.returnFail(100, "用户不存在");
        }
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        RedisKey redisKey = new RedisKey(Constants.CLUB_SYSTEM, getLotteryNLRedisKey(uid));
        try {
            if (redisTemplate.exists(redisKey)) {
                int dcount = redisTemplate.get(redisKey)==null?0:(Integer.valueOf((redisTemplate.get(redisKey).toString())));
                if (dcount >= 20) {
                    return APIResponse.returnFail(103, "今天已经抽够20次了，明天再来吧！");
                }
            }

            TbSystemParametersExample sysExample = new TbSystemParametersExample();
            sysExample.createCriteria().andParamKeyEqualTo("operate.lottery.newyear.start.time");
            TbSystemParameters startTime = systemParametersMapper.selectByExample(sysExample).get(0);
            if (now.before(sdf.parse(startTime.getParamValue()))) {
                return APIResponse.returnFail(101, "抽奖活动未开始");
            }
            sysExample.clear();
            sysExample.createCriteria().andParamKeyEqualTo("operate.lottery.newyear.end.time");
            TbSystemParameters endTime = systemParametersMapper.selectByExample(sysExample).get(0);
            if (now.after(sdf.parse(endTime.getParamValue()))){
                return APIResponse.returnFail(101, "抽奖活动已经结束");
            }
        } catch (ParseException e) {
            logger.warn("未配置抽奖活动开始结束时间");
            return APIResponse.returnFail(101, "活动还未开始");
        }
//        TbOperateLotteryLimitExample limitExample = new TbOperateLotteryLimitExample();
//        limitExample.createCriteria().andMobileEqualTo(userInfo.getMobile());
//        if (lotteryLimitMapper.countByExample(limitExample) > 0){
//            return APIResponse.returnFail(106,  "嘿嘿，百灵鸟的小伙伴好好努力工作吧，就是不让你抽奖！");
//        }

        //2. 扣除10鸟蛋
        ReqUserAccumulateModify modify = new ReqUserAccumulateModify();
        modify.setUid(userInfo.getUid());
        modify.setAssetsType(AssetsType.ASSETS_EGGS.id.byteValue());
        modify.setSystemCode(Constants.OPERATIVE_SYSTEM_CODE);
        modify.setReceiver("百灵鸟");
        modify.setPayReceive("运营活动消耗");
        modify.setBusinessCode(Constants.OPERATIVE_NEW_YEAR_LOTTERY_SUBEGG_CODE);
        modify.setAccumulate(10L);
        modify.setInfo("大转盘抽奖");
        APIRequest<ReqUserAccumulateModify> apiRequest = new APIRequest<>();
        apiRequest.setData(modify);
        APIResponse<RespUserAccumulateModify> response = userAssetsService.modifyAccumulate(apiRequest);
        if (!response.isRet()){
            logger.warn("扣除鸟蛋时出错：" + JSON.toJSONString(response));
            return APIResponse.returnFail(104, "鸟蛋不足");  //扣除鸟蛋失败
        }

        //3. 开始抽奖:
        RespHitPrizeInfo hitPrizeInfo = new RespHitPrizeInfo();  //中奖信息
        hitPrizeInfo.setUid(uid);
        hitPrizeInfo.setMobile(userInfo.getMobile());
        //奖品列表
        TbOperateLotteryPrizeItemsExample itemExample = new TbOperateLotteryPrizeItemsExample();
        itemExample.createCriteria().andTypeEqualTo(1); //新年抽奖
        itemExample.setOrderByClause(" rate asc");
        List<TbOperateLotteryPrizeItems> prizeItems = lotteryPrizeItemsMapper.selectByExample(itemExample);
        Map<Integer, Double> IDRateMap = new TreeMap<>();
        for (TbOperateLotteryPrizeItems prizeItem : prizeItems){
            IDRateMap.put(prizeItem.getId(), prizeItem.getRate());
        }
        //算出此次中奖的奖品
        LotteryRateListUtil lotteryRateListUtil = new LotteryRateListUtil(IDRateMap);
        int prizeId = lotteryRateListUtil.hitLotteryRate();
        TbOperateLotteryPrizeItems hitPrizeItem = lotteryPrizeItemsMapper.selectByPrimaryKey(prizeId);
        if (hitPrizeItem == null){
            return APIResponse.returnFail(101, "抽奖活动未开始");  //无此奖品
        }
        logger.warn("抽中：prizeId=" + prizeId + ", prizeName=" + hitPrizeItem.getPrizeDesc());
        boolean hitPrize = false;
        if (hitPrizeItem.getIsAward()){        //中奖奖品不是谢谢参与之类
            //扣减库存
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("prizeId", prizeId);
            int updateRet = sqlSessionTemplate.update("updateLotteryPrizeNumberNewYear", paramMap);
            if (updateRet <= 0) {
                logger.warn("prizeId=" + prizeId + "没有库存！");
                hitPrize = false;           //未中奖： 奖品没有库存，算此人谢谢参与
            } else {                        //中  奖： 记录中奖信息
                hitPrizeInfo.setPrizeId(prizeId);
                hitPrizeInfo.setPrizeLevel(hitPrizeItem.getLevelName());
                hitPrizeInfo.setPrizeName(hitPrizeItem.getPrizeDesc());
                hitPrize = true;
            }
        }
        if (!hitPrize) {        //没有中奖，给谢谢参与
            itemExample.clear();
            itemExample.createCriteria().andTypeEqualTo(1).andIsAwardEqualTo(false);
            TbOperateLotteryPrizeItems blankPrize = lotteryPrizeItemsMapper.selectByExample(itemExample).get(0);
            hitPrizeInfo.setPrizeId(blankPrize.getId());
            hitPrizeInfo.setPrizeLevel(blankPrize.getLevelName());
            hitPrizeInfo.setPrizeName(blankPrize.getPrizeDesc());
        }

        //4. 记录抽奖信息，发虚拟奖品
        TbOperateLotteryPrizeRecord record = new TbOperateLotteryPrizeRecord();
        record.setCostEggs(10);
        record.setMobile(userInfo.getMobile());
        record.setUid(userInfo.getUid());
        record.setPrizeItemId(hitPrizeItem.getId());
        record.setType(1);       //新年抽奖
        if (hitPrize) {     //如果中奖了
            record.setPrizeName(hitPrizeItem.getPrizeDesc());
            record.setHitPrize(true);
            try {
                //推送消息，发短信
                cppService.pushClubCommonMsg(
                        userInfo.getIcon(),
                        "恭喜您，刚刚抽中了\"" + hitPrizeItem.getPrizeDesc() + "\"，百灵鸟工作人员将在7个工作日内通过电话或微信与您联系，请保持手机畅通！",
                        Arrays.asList(userInfo.getUid()));
                //smsService.sendMessageToPhone(userInfo.getMobile(), SmsApi.MESSAGE_TEMPLATE_OPERATIVE_NEWYEAR_LOTTERY_NOTICE, new String[]{"\"" + hitPrizeItem.getPrizeDesc() + "\""}, true);
            }catch (Exception e){
                e.printStackTrace();
                logger.warn("发送中奖消息异常：uid={}, msg={}, prizeId=", uid, e.getMessage(), hitPrizeItem.getId());
            }

            //如果是优惠券，发送优惠券到此用户账户
            if (hitPrizeItem.getLevel() == 3) {
                itemExample.clear();
                itemExample.createCriteria().andTypeEqualTo(1).andLevelEqualTo(3);  //大转盘活动，等级为三，优惠券
                itemExample.setOrderByClause(" id asc");
                List<TbOperateLotteryPrizeItems> _3LevelPrize = lotteryPrizeItemsMapper.selectByExample(itemExample);
                if (_3LevelPrize != null && _3LevelPrize.size() == 2){
                    ObtainCouponsParamsVo vo = new ObtainCouponsParamsVo();
                    vo.setUid(uid);
                    if (_3LevelPrize.get(0).getId().intValue() == hitPrizeItem.getId().intValue()) {
                        vo.setActivityCouponType(ActivityCouponType.BIG_WHEEL_PLACE_8);
                    }
                    if (_3LevelPrize.get(1).getId().intValue() == hitPrizeItem.getId().intValue()) {
                        vo.setActivityCouponType(ActivityCouponType.BIG_WHEEL_PLACE_5);
                    }
                    APIResponse<CouponInfoVo> counponResp = couponService.obtainCoupons(vo);
                    if (!counponResp.isRet()) {
                        logger.warn("发中奖优惠券失败：uid={}, prizeId={}, return={}", uid, prizeId, JSON.toJSON(counponResp));
                    }else {
                        logger.warn("发中奖优惠券：uid={}, prizeId={}, 发放优惠券成功", uid, prizeId);
                    }
                }
            }
        }else {
            record.setHitPrize(false);
            record.setPrizeName("谢谢参与");
        }
        lotteryPrizeRecordMapper.insertSelective(record);
        hitPrizeInfo.setRid(record.getId());

//        clubRedisTemplate.incr(redisKey.getRedisKey());      //抽奖次数加1
        Object value = redisTemplate.get(redisKey);
        int count = value ==null?1:(Integer.valueOf(value.toString())+1);
        redisTemplate.set(redisKey, count);
        logger.warn("uid={}, 今天抽奖次数：{}", uid, redisTemplate.get(redisKey));
        System.out.println("uid="+uid+", 今天抽奖次数："+ count);

        return APIResponse.returnSuccess(hitPrizeInfo);
    }


    @Override
    public APIResponse drawLottery(int uid) {

        RespUserInfoBase userInfo = getUserInfoBase(uid);
        if (userInfo == null){
            return APIResponse.returnFail(100, "用户不存在");
        }

        //1. 判断此用户是否有抽奖资格
        APIResponse validateResp = validateDrawLottery(uid);
        if (!validateResp.isRet()){
            return validateResp;
        }

        //2. 是否已经使用过免费抽奖次数，如果已经使用，需扣除10鸟蛋来进行抽奖
        long costEggs = 0L;
        if (redisTemplate.exists(getFreeLotteryTagRedisKey(uid))){
            //扣除10鸟蛋
            APIResponse<RespUserAccumulateModify> response = deductOrIncrEggs(userInfo, -10L);
            if (!response.isRet()){
                logger.warn("扣除鸟蛋时出错：" + JSON.toJSONString(response));
                return APIResponse.returnFail(104, "鸟蛋不足");  //扣除鸟蛋失败
            }
            costEggs = 10;
        }

        //中奖信息
        RespHitPrizeInfo hitPrizeInfo = new RespHitPrizeInfo();
        hitPrizeInfo.setUid(uid);
        hitPrizeInfo.setMobile(userInfo.getMobile());

        //3. 开始抽奖:
        //奖品列表
        TbOperateLotteryPrizeItemsExample itemExample = new TbOperateLotteryPrizeItemsExample();
        itemExample.createCriteria().andTypeEqualTo(0); //主席双旦抽奖
        itemExample.setOrderByClause(" rate asc");
        List<TbOperateLotteryPrizeItems> prizeItems = lotteryPrizeItemsMapper.selectByExample(itemExample);
        Map<Integer, Double> IDRateMap = new TreeMap<>();
        for (TbOperateLotteryPrizeItems prizeItem : prizeItems){
            IDRateMap.put(prizeItem.getId(), prizeItem.getRate());
        }
        //算出此次中奖的奖品
        LotteryRateListUtil lotteryRateListUtil = new LotteryRateListUtil(IDRateMap);
        int prizeId = lotteryRateListUtil.hitLotteryRate();
        Collections.sort(prizeItems, new Comparator<TbOperateLotteryPrizeItems>() {
            @Override
            public int compare(TbOperateLotteryPrizeItems o1, TbOperateLotteryPrizeItems o2) {
                return o2.getLevel() - o1.getLevel();
            }
        });
        if (prizeId == -1){
            return APIResponse.returnFail(100, "抽奖活动未开始");
        }
        TbOperateLotteryPrizeItems prize = lotteryPrizeItemsMapper.selectByPrimaryKey(prizeId);
        int blankPrizeId = prizeItems.get(0).getId(); //谢谢参与
        TbOperateLotteryPrizeItems blankPrize = lotteryPrizeItemsMapper.selectByPrimaryKey(blankPrizeId);
        logger.warn("prizeId=" + prizeId + ", blankPrizeId=" + blankPrizeId);

        boolean hitPrize = false;

        //4. 判断此奖品今天是否有库存
        if (prizeId != blankPrizeId) { //未随机到非“谢谢参与”奖项
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("prizeId", prizeId);
            int updateRet = sqlSessionTemplate.update("updateLotteryPrizeNumber", paramMap);
            if (updateRet <= 0) {
                hitPrize = false;           //未中奖： 奖品没有库存
                hitPrizeInfo.setPrizeId(blankPrizeId);
                hitPrizeInfo.setPrizeLevel(blankPrize.getLevelName());
                hitPrizeInfo.setPrizeName(blankPrize.getPrizeDesc());
            } else {                        //中  奖： 记录中奖信息
                hitPrizeInfo.setPrizeId(prizeId);
                hitPrizeInfo.setPrizeLevel(prize.getLevelName());
                hitPrizeInfo.setPrizeName(prize.getPrizeDesc());
                hitPrize = true;
            }
        }else {
            hitPrizeInfo.setPrizeId(blankPrizeId);
            hitPrizeInfo.setPrizeLevel(blankPrize.getLevelName());
            hitPrizeInfo.setPrizeName(blankPrize.getPrizeDesc());
        }
        hitPrizeInfo.setHitPirze(hitPrize);

        //5. 记录此用户今天已经抽奖
        redisTemplate.set(getLotteryUidRedisKey(uid), System.currentTimeMillis());
        redisTemplate.setnx(getFreeLotteryTagRedisKey(uid), uid);       //标记已使用了免费抽奖次数
        logger.warn("hitPrizeInfo=" + JSON.toJSONString(hitPrizeInfo));

        //6. 异步处理：记录中奖的用户信息，更新中奖列表，如果中了鸟蛋发放鸟蛋
//        executor.submit(new GotPrizeProcessThread(
//                userInfo, lotteryPrizeRecordMapper, prize, redisTemplate, userAssetsService, costEggs, hitPrize));
        int rid = recordLottery(costEggs, userInfo, prize, hitPrize);
        hitPrizeInfo.setRid(rid);       //返回给客户端抽奖记录id
        return APIResponse.returnSuccess(hitPrizeInfo);
    }

    @Autowired
    private PullClubMapper pullClubMapper;
    @Autowired
    private TbChannelUserMapper channelUserMapper;

    /**
     * 俱乐部，拉新抽奖
     * @param oldUid    老俱乐部主席uid
     * @param newClubId 新俱乐部id
     * @return
     */
    @Override
    public APIResponse drawLotteryPullNewClub(int oldUid, int newClubId){

        //1. 入参校验
        RespUserInfoBase userInfo = getUserInfoBase(oldUid);
        if (userInfo == null){
            return APIResponse.returnFail(100, "用户不存在");
        }
        TbClub tbClub = clubMapper.selectByPrimaryKey(newClubId);
        if (tbClub == null){
            return APIResponse.returnFail("俱乐部不存在或者被解散！");
        }

        //2. 抽奖次数校验
        TbChannelUserExample channelUserExample = new TbChannelUserExample();
        channelUserExample.createCriteria()
                .andOldClubUidEqualTo(oldUid)
                .andClubIdEqualTo(newClubId);
        List<TbChannelUser> channelUsers = channelUserMapper.selectByExample(channelUserExample);
        if (channelUsers == null || channelUsers.size() == 0){
            return APIResponse.returnFail("拉新俱乐部异常！");
        }
        int usableDrawCount = channelUsers.get(0).getDrawCount();
        if (usableDrawCount == 0){
            return APIResponse.returnFail("无可用抽奖次数！");
        }

        //3. 开始抽奖:
        //奖品列表
        TbOperateLotteryPrizeItemsExample itemExample = new TbOperateLotteryPrizeItemsExample();
        itemExample.createCriteria().andTypeEqualTo(0); //老带薪俱乐部主席抽奖
        itemExample.setOrderByClause(" rate asc");
        List<TbOperateLotteryPrizeItems> prizeItems = lotteryPrizeItemsMapper.selectByExample(itemExample);
        Map<Integer, Double> IDRateMap = new TreeMap<>();
        for (TbOperateLotteryPrizeItems prizeItem : prizeItems){
            IDRateMap.put(prizeItem.getId(), prizeItem.getRate());
        }
        //算出此次中奖的奖品
        LotteryRateListUtil lotteryRateListUtil = new LotteryRateListUtil(IDRateMap);
        int hitPrizeId = lotteryRateListUtil.hitLotteryRate();
        TbOperateLotteryPrizeItems hitPrizeItem = lotteryPrizeItemsMapper.selectByPrimaryKey(hitPrizeId);
        if (hitPrizeItem == null){
            return APIResponse.returnFail(101, "抽奖活动未开始");  //后台没有配置此奖品，活动没开始
        }
        logger.warn("抽中：prizeId=" + hitPrizeId + ", prizeName=" + hitPrizeItem.getPrizeDesc());

        //4. 扣减可用抽奖次数
        int ret = pullClubMapper.updateDrawCountOfPullClub(oldUid, newClubId);
        if (ret != 1){
            return APIResponse.returnFail("无可用抽奖次数！");
        }

        //5. 中奖信息包装
        RespHitPrizeInfo hitPrizeInfo = new RespHitPrizeInfo();  //中奖信息
        hitPrizeInfo.setUid(oldUid);
        hitPrizeInfo.setMobile(userInfo.getMobile());
        boolean hitPrize = false;
        if (hitPrizeItem.getIsAward()) {        //中奖奖品不是谢谢参与之类
            //扣减库存
            int ret2 = pullClubMapper.updateLotteryStore(hitPrizeId);
            if (ret2 != 1){
                //没有库存了
                logger.warn("prizeId=" + hitPrizeId + "没有库存！");
                hitPrize = false;           //未中奖： 奖品没有库存，算此人谢谢参与
                itemExample.clear();
                itemExample.createCriteria().andTypeEqualTo(0).andIsAwardEqualTo(false);
                TbOperateLotteryPrizeItems blankPrize = lotteryPrizeItemsMapper.selectByExample(itemExample).get(0);
                hitPrizeInfo.setPrizeId(blankPrize.getId());
                hitPrizeInfo.setPrizeLevel("谢谢参与！");
                hitPrizeInfo.setPrizeName("谢谢参与！");
            }else {     //中奖
                hitPrizeInfo.setPrizeId(hitPrizeId);
                hitPrizeInfo.setPrizeLevel(hitPrizeItem.getLevelName());
                hitPrizeInfo.setPrizeName(hitPrizeItem.getPrizeDesc());
                hitPrize = true;
            }
        }else {
            hitPrizeInfo.setPrizeId(hitPrizeItem.getId());
            hitPrizeInfo.setPrizeLevel("谢谢参与！");
            hitPrizeInfo.setPrizeName("谢谢参与！");
        }
        hitPrizeInfo.setHitPirze(hitPrize);

        //6. 记录中奖信息，发放虚拟中奖奖品
        int rid = recordLottery(0, userInfo, hitPrizeItem, hitPrize);
        hitPrizeInfo.setRid(rid);

        return APIResponse.returnSuccess(hitPrizeInfo);
    }

    /**
     * 校验是否可以参加抽奖
     */
    private APIResponse validateDrawLottery(int uid){

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startTime = null;
        try {
            startTime = sdf.parse("2016-12-24 00:00:00");
            Date now = new Date();
            if (now.before(startTime)){
                return APIResponse.returnFail("抽奖活动还未开始！");
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if (redisTemplate.exists(getLotteryUidRedisKey(uid))){
            return APIResponse.returnFail(101, "今天已经抽过奖了！");
        }

        TbOperateLotteryLimitExample limitExample = new TbOperateLotteryLimitExample();
        RespUserInfoBase userInfo = getUserInfoBase(uid);
        if (userInfo == null || userInfo.getMobile() ==null){
            return APIResponse.returnFail("107", "用户不存在");
        }
        limitExample.createCriteria().andMobileEqualTo(userInfo.getMobile());
        if (lotteryLimitMapper.countByExample(limitExample) > 0){
            return APIResponse.returnFail(106,  "嘿嘿，百灵鸟的小伙伴好好努力工作吧，就是不让你抽奖！");
        }

        TbClubExample example = new TbClubExample();
        example.createCriteria()
                .andUidEqualTo(uid).andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        int count = clubMapper.countByExample(example);
        if (count <=0 ){
            return APIResponse.returnFail(102, "不是俱乐部主席身份");
        }

        //是主席身份，检查这些俱乐部是否结算过非0元订单活动
        List<TbClub> clubList = clubMapper.selectByExample(example);
        List<Integer> clubIds = new ArrayList<>();
        for (TbClub club : clubList){
            clubIds.add(club.getId());
        }
        TbClubActivitySettlementExample activitySettlementExample = new TbClubActivitySettlementExample();
        activitySettlementExample.createCriteria()
                .andClubIdIn(clubIds).andDealMoneyGreaterThanOrEqualTo(new BigDecimal(1));
        int settleCount = clubActivitySettlementMapper.countByExample(activitySettlementExample);
        if (settleCount <= 0){
            return APIResponse.returnFail(103, "没有非0元活动结算记录");
        }

        return APIResponse.returnSuccess();
    }

    private int recordLottery(long costEggs, RespUserInfoBase userInfo, TbOperateLotteryPrizeItems prize, boolean hitPrize){
        //记录抽奖信息
        TbOperateLotteryPrizeRecord record = new TbOperateLotteryPrizeRecord();
        record.setCostEggs((int)costEggs);
        record.setMobile(userInfo.getMobile());
        record.setUid(userInfo.getUid());
        record.setPrizeItemId(prize.getId());
        record.setPrizeName(prize.getPrizeDesc());
        record.setType(0);  //俱乐部双旦抽奖
        if (hitPrize) {     //如果中奖了
            record.setHitPrize(true);
        }else {
            record.setHitPrize(false);
        }
        lotteryPrizeRecordMapper.insertSelective(record);
        //记录中奖信息
        if (hitPrize) {
            if (prize.getLevel() == 3) {        //安慰奖：发放鸟蛋20个
                deductOrIncrEggs(userInfo, 20);
                cppService.pushClubCommonMsg(
                        userInfo.getIcon(),
                        "感谢您的参与，本次俱乐部老带新活动抽奖获得\"" + prize.getPrizeDesc() + "\"，20鸟蛋已发放至您的账户中！", Arrays.asList(userInfo.getUid()));
            }else {
                //推送中奖消息
                cppService.pushClubCommonMsg(
                        userInfo.getIcon(),
                        "感谢您的参与，本次俱乐部老带新活动抽奖获得\"" + prize.getPrizeDesc() + "\"！",
                        Arrays.asList(userInfo.getUid()));
            }
        }
        return record.getId();
    }
    /**
     * 扣除鸟蛋10个才可以参加抽奖
     */
    private APIResponse<RespUserAccumulateModify> deductOrIncrEggs(RespUserInfoBase userInfo, long egg){
        ReqUserAccumulateModify modify = new ReqUserAccumulateModify();
        modify.setUid(userInfo.getUid());
        modify.setAssetsType(AssetsType.ASSETS_EGGS.id.byteValue());
        modify.setSystemCode(Constants.CLUB_SYSTEM_CODE);
        String userName = userInfo.getNickName();
        modify.setReceiver(userName);
        if (egg > 0){
            modify.setPayReceive("俱乐部抽奖奖励");
            modify.setReceiver(userInfo.getNickName());
            modify.setBusinessCode(ClubConstants.CLUB_LOTTERY_ADDEGG_CODE);
            modify.setAccumulate(egg);
        }else {
            modify.setReceiver("百灵鸟");
            modify.setPayReceive("俱乐部抽奖支出");
            modify.setBusinessCode(ClubConstants.CLUB_LOTTERY_SUBEGG_CODE);
            modify.setAccumulate(-1*egg);
        }
        modify.setInfo("俱乐部抽奖");

        APIRequest<ReqUserAccumulateModify> apiRequest = new APIRequest<>();
        apiRequest.setData(modify);

        return userAssetsService.modifyAccumulate(apiRequest);
    }

    @Override
    public List<TbOperateLotteryPrizeRecord> queryHitRecordList() {
        List<TbOperateLotteryPrizeRecord> records = new ArrayList<>();
        TbOperateLotteryPrizeRecordExample example = new TbOperateLotteryPrizeRecordExample();
        example.createCriteria()
                .andTypeEqualTo(0)
                .andHitPrizeEqualTo(true);
        example.setOrderByClause("id desc");
        records = lotteryPrizeRecordMapper.selectByExample(example);
        return records;
    }

    @Override
    public List<TbOperateLotteryPrizeRecord> queryHitRecordListPullNewClub(int uid) throws ParseException {
        List<TbOperateLotteryPrizeRecord> records = new ArrayList<>();
        RespUserInfoBase userInfo = getUserInfoBase(uid);
        if (userInfo == null){
            return records;
        }
        TbOperateLotteryPrizeRecordExample example = new TbOperateLotteryPrizeRecordExample();
        example.createCriteria()
                .andMobileEqualTo(userInfo.getMobile())
                .andTypeEqualTo(0)
                .andHitPrizeEqualTo(true)
                .andCreateTimeGreaterThan(new SimpleDateFormat("yyyy-MM-dd").parse("2017-01-01"));
        example.setOrderByClause("id desc");
        records = lotteryPrizeRecordMapper.selectByExample(example);
        return records;
    }

    @Override
    public List<TbOperateLotteryPrizeRecord> queryHitRecordListNewYear() {
        List<TbOperateLotteryPrizeRecord> records = new ArrayList<>();
        TbOperateLotteryPrizeRecordExample example = new TbOperateLotteryPrizeRecordExample();
        example.createCriteria()
                .andTypeEqualTo(1)
                .andHitPrizeEqualTo(true);
        example.setOrderByClause("id desc");
        records = lotteryPrizeRecordMapper.selectByExample(example);
        return records;
    }

    @Override
    public void recordHitPrizeUserInfo(int rid, int uid, String mobile, String address) {
        TbOperateLotteryPrizeRecord record = lotteryPrizeRecordMapper.selectByPrimaryKey(rid);
        if (record == null){
            return;
        }
        if (record.getUid() != uid || !record.getHitPrize()){
            throw new BizException("非法数据！");
        }
        record.setMobileInput(mobile);
        record.setAddress(address);

        lotteryPrizeRecordMapper.updateByPrimaryKeySelective(record);
    }
}
